package com.bdd.service.Impl;

import com.bdd.Enum.DiscountEnum;
import com.bdd.entity.*;
import com.bdd.mapper.*;
import com.bdd.model.bo.OrderItemBO;
import com.bdd.model.bo.clothing.ClothingForOrderItemBO;
import com.bdd.model.bo.order.OrderItemListBO;
import com.bdd.service.OrderItemService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

@Service
public class OrderItemServiceImpl implements OrderItemService {

    @Autowired
    OrderItemDao orderItemDao;

    @Autowired
    InventoryDao inventoryDao;

    @Autowired
    ClothingDao clothingDao;

    @Autowired
    OrderDao orderDao;

    @Autowired
    SizeDao sizeDao;

    @Autowired
    PaymentDao paymentDao;

    private CopyOnWriteArrayList<ClothingForOrderItemBO> itemBOList = new CopyOnWriteArrayList<>();



    private ConcurrentHashMap<Integer, List<ClothingForOrderItemBO>> userItemsMap = new ConcurrentHashMap<>();


    @Override
    public List<ClothingForOrderItemBO> list() {
        List<ClothingForOrderItemBO> itemList = itemBOList;
        return itemList;
    }

    @Override
    public OrderItemBO searchById(Integer id) {
        OrderItemBO bo = orderItemDao.selectBOByPrimaryKey(id);
        return bo;
    }

    @Override
    public void addToCache(Integer id, String sizeStr) {
        Size size = sizeDao.selectBySpecs(sizeStr);


        ClothingForOrderItemBO clothingForOrderItemBO = itemBOList.stream()
                .filter(itemListBO -> itemListBO.getId() == id)
                .findAny()
                .orElse(null);
        if (!Objects.isNull(clothingForOrderItemBO)) {
            clothingForOrderItemBO.setCount(clothingForOrderItemBO.getCount() + 1);
            itemBOList = itemBOList.stream()
                    .filter(itemListBO -> itemListBO.getId() != id)
                    .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
            itemBOList.add(clothingForOrderItemBO);
            return;
        }
        ClothingForOrderItemBO bo = clothingDao.selectCFOBO(id, size.getId());
        if(ObjectUtils.isEmpty(bo)){
            throw new IllegalArgumentException("该商品没有该对应规格");
        }
        if(bo.getDiscount()!=null){
            double disdountRate = DiscountEnum.getDiscountByName(bo.getDiscount());
            double newPrice = bo.getOldPrice() * disdountRate;
        }
        bo.setNewPrice(bo.getOldPrice());
        bo.setCount(1);
        itemBOList.add(bo);
        return;
    }

    @Override
    public void delete(Integer id) {
        itemBOList = itemBOList.stream()
                .map(orderItemListBO -> {
                    if (orderItemListBO.getId() == id) orderItemListBO.setCount(orderItemListBO.getCount() - 1);
                    return orderItemListBO;
                })
                .filter(clothingForOrderItemBO -> clothingForOrderItemBO.getCount() != 0)
                .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
    }

    @Override
    public Integer settlement(Integer userId) {
        //插入订单
//        List<ClothingForOrderItemBO> itemBOList = userItemsMap.get(userId);
        Double totalPrice = 0d;
        Double discountAmount = 0d;
        for (ClothingForOrderItemBO bo : itemBOList) {
            totalPrice += bo.getNewPrice() * bo.getCount();
            discountAmount += (bo.getOldPrice() - bo.getNewPrice()) * bo.getCount();
        }
        Order order = com.bdd.entity.Order.builder()
                .totalPrice(totalPrice)
                .discountAmount(discountAmount)
                .build();
        orderDao.insertSelective(order);


        for (ClothingForOrderItemBO bo : itemBOList) {
            String sizeStr = bo.getSize();
            //插入订单项
            Size size = sizeDao.selectBySpecs(sizeStr);

            OrderItem orderItem = OrderItem.builder()
                    .discountAmount(bo.getOldPrice().intValue() * bo.getCount() - bo.getNewPrice().intValue() * bo.getCount())
                    .purchasePrice(bo.getNewPrice() * bo.getCount())
                    .clothingId(bo.getId())
                    .count(bo.getCount())
                    .orderId(order.getId())
                    .sizeId(size.getId())
                    .status("NOTPAID")
                    .build();
            orderItemDao.insertSelective(orderItem);

            //更新库存
            Inventory inventory = inventoryDao.selectByCothingId(orderItem.getClothingId());
            inventory.setQuantity(inventory.getQuantity() - bo.getCount());
            inventoryDao.updateByPrimaryKey(inventory);
        }
        itemBOList.clear();
        return order.getId();
    }


    @Override
    @Transactional
    public void pay(Integer orderId) {
        Order order = orderDao.selectByPrimaryKey(orderId);
        List<OrderItemListBO>orderItemList = orderItemDao.selectBOListByOrderId(orderId);
        for (OrderItemListBO orderItemBo : orderItemList){
            OrderItem orderItem = orderItemDao.selectByPrimaryKey(orderItemBo.getOrderItemId());
            orderItem.setStatus("PAID");
            orderItemDao.updateByPrimaryKey(orderItem);
        }
        Payment payment = Payment.builder()
                .totalPrice(order.getTotalPrice())
                .orderId(order.getId())
                .status(new Byte("1"))
                .build();
        paymentDao.insert(payment);
    }

    @Override
    public void deleteByOrderId(Integer orderId) {
        orderItemDao.deleteByOrderId(orderId);
    }

    static class OrderItemListMapUtil {
        static OrderItem boTodo(OrderItemListBO bo) {
            OrderItem orderItem = OrderItem.builder()
                    .id(bo.getOrderItemId())
                    .discountAmount(bo.getOldPrice().intValue() - bo.getNewPrice().intValue())
                    .purchasePrice(bo.getNewPrice())
                    .clothingId(bo.getId())
                    .count(bo.getCount())
                    .orderId(bo.getOrderItemOrderId())
                    .sizeId(bo.getSizeId())
                    .build();
            return orderItem;
        }
    }

    static class OrderItemMapUtil {
        static List<OrderItemBO> dolisttobolist(List<OrderItem> orderItemList) {
            List<OrderItemBO> boList = orderItemList.stream().map(orderItem -> {
                OrderItemBO bo = doToBo(orderItem);
                return bo;
            }).collect(Collectors.toList());
            return boList;
        }

        static OrderItem boTodo(OrderItemBO bo) {
            OrderItem orderItem = OrderItem.builder()
                    .orderId(bo.getOrderId())
                    .id(bo.getId())
                    .discountAmount(bo.getDiscountAmount())
                    .purchasePrice(bo.getPurchasePrice())
                    .clothingId(bo.getClothingId())
                    .count(bo.getCount())
                    .build();
            return orderItem;
        }

        static OrderItemBO doToBo(OrderItem orderItem) {
            OrderItemBO orderItemBO = OrderItemBO.builder()
                    .id(orderItem.getId())
                    .orderId(orderItem.getOrderId())
                    .discountAmount(orderItem.getDiscountAmount())
                    .purchasePrice(orderItem.getPurchasePrice())
                    .clothingId(orderItem.getClothingId())
                    .count(orderItem.getCount())
                    .build();
            return orderItemBO;
        }


    }
}
